#ifndef _ENTITY_H
#define _ENTITY_H

#include <memory>
#include <string>
#include "RenderManager.h"

enum MoveStateX
{
	MSX_LEFT = 0,
	MSX_RIGHT,
	MSX_NONE
};

enum MoveStateY
{
	MSY_UP = 0,
	MSY_DOWN,
	MSY_NONE
};

enum EntityFlags
{
	GHOST				= 0x0001,	// ignore collision
	INPUT_ENABLED		= 0x0002,	
	MOVEABLE			= 0x0004,
	GRAVITY_AFFECTED	= 0x0008,
	IS_IN_WATER			= 0x0010,
	JUST_LANDED			= 0x0020,
	LADDER_BELOW		= 0x0040,
	LADDER_COLLISION	= 0x0080,
	COLLISION_HIT_LEFT	= 0x0100,
	COLLISION_HIT_RIGHT = 0x0200,
	TAKE_DAMAGE			= 0x0400
};

enum EntityComponent
{
	COMPONENT_COLLIDEABLE			= 0x0001,
	COMPONENT_DRAWABLE				= 0x0002,
	COMPONENT_WORLD_COLLISION		= 0x0004
};

enum VelocityType
{
	VELOCITY_NORMAL = 0,
	VELOCITY_AFTER_MOVEMENT,
	VELOCITY_AFTER_MOVEMENT_X,
	VELOCITY_AFTER_MOVEMENT_Y,
	FLOOR_SENSOR,
	FLOOR_SENSOR_AFTER_MOVEMENT,
	FLOOR_SENSOR_AFTER_MOVEMENT_X,
	FLOOR_SENSOR_AFTER_MOVEMENT_Y,
	GROUND_SENSOR,
	GROUND_SENSOR_AFTER_MOVEMENT,
	GROUND_SENSOR_AFTER_MOVEMENT_X,
	GROUND_SENSOR_AFTER_MOVEMENT_Y,
	LEFT_SENSOR,
	RIGHT_SENSOR
};

/*enum CollisionType
{
	COLLISION_GROUND = 0,
	COLLISION_TOP,
	COLLISION_LEFT,
	COLLISION_RIGHT
};*/

class Entity
{
public:
	Entity(void){}
	virtual ~Entity(void){}

	virtual void move() = 0;
	virtual void update() = 0;
	//virtual void draw(RenderManager* renderManager) = 0;
	virtual void initialize() = 0;
	virtual void clean() = 0;

	//virtual sf::FloatRect collisionBox(int type = 0) = 0;

	sf::Vector2f& getDimension() { return _dimension; }
	std::string& getType() { return _type; }
	const sf::Sprite& getSprite() { return _sprite; }
	bool killMe() { return _killMe; }

	bool isMoving()
	{  
		if (_velocity.x == 0.0f && _velocity.y == 0.0f)
			return false;
		return true;
	}

	const int flags() { return _flags; }
	const int component() { return _component; }
	const float mass() { return _mass; }
	
	void setPosition(float x, float y)
	{
		_position.x = x;
		_position.y = y;
	}

	void setPosition(const sf::Vector2f& position)
	{
		_position = position;
	}

	void translate(float x, float y)
	{
		_velocity.x += x;
		_velocity.y += y;
	}

	void translate(const sf::Vector2f& translation)
	{
		_velocity += translation;
	}

	sf::Vector2f _position;
	sf::Vector2f _velocity;
	bool _onGround;
	bool _ignoreCollision;

	void setFlag(int value)
	{
		if ((GHOST & value) == GHOST)
			_flags |= GHOST;
		else if ((INPUT_ENABLED & value) == INPUT_ENABLED)
			_flags |= INPUT_ENABLED;
		else if ((MOVEABLE & value) == MOVEABLE)
			_flags |= MOVEABLE;
		else if ((GRAVITY_AFFECTED & value) == GRAVITY_AFFECTED)
			_flags |= GRAVITY_AFFECTED;
		else if ((IS_IN_WATER & value) == IS_IN_WATER)
			_flags |= IS_IN_WATER;
		else if ((JUST_LANDED & value) == JUST_LANDED)
			_flags |= JUST_LANDED;
		else if ((LADDER_BELOW & value) == LADDER_BELOW)
			_flags |= LADDER_BELOW;
		else if ((LADDER_COLLISION & value) == LADDER_COLLISION)
			_flags |= LADDER_COLLISION;
		else if ((COLLISION_HIT_LEFT & value) == COLLISION_HIT_LEFT)
			_flags |= COLLISION_HIT_LEFT;
		else if ((COLLISION_HIT_RIGHT & value) == COLLISION_HIT_RIGHT)
			_flags |= COLLISION_HIT_RIGHT;
		else if ((TAKE_DAMAGE & value) == TAKE_DAMAGE)
			_flags |= TAKE_DAMAGE;
	}

	void removeFlag(int value)
	{
		if ((GHOST & value) == GHOST)
			_flags = _flags & ~GHOST;
		else if ((INPUT_ENABLED & value) == INPUT_ENABLED)
			_flags = _flags & ~INPUT_ENABLED;
		else if ((MOVEABLE & value) == MOVEABLE)
			_flags = _flags & ~MOVEABLE;
		else if ((GRAVITY_AFFECTED & value) == GRAVITY_AFFECTED)
			_flags = _flags & ~GRAVITY_AFFECTED;
		else if ((IS_IN_WATER & value) == IS_IN_WATER)
			_flags = _flags & ~IS_IN_WATER;
		else if ((JUST_LANDED & value) == JUST_LANDED)
			_flags = _flags & ~JUST_LANDED;
		else if ((LADDER_BELOW & value) == LADDER_BELOW)
			_flags = _flags & ~LADDER_BELOW;
		else if ((LADDER_COLLISION & value) == LADDER_COLLISION)
			_flags = _flags & ~LADDER_COLLISION;
		else if ((COLLISION_HIT_LEFT & value) == COLLISION_HIT_LEFT)
			_flags = _flags & ~COLLISION_HIT_LEFT;
		else if ((COLLISION_HIT_RIGHT & value) == COLLISION_HIT_RIGHT)
			_flags = _flags & ~COLLISION_HIT_RIGHT;
		else if ((TAKE_DAMAGE & value) == TAKE_DAMAGE)
			_flags = _flags & ~TAKE_DAMAGE;
	}

	int getMovementStateX() { return _msX; }
	int getMovementStateY() { return _msY; }

	void applyTranslation()
	{
		_position += _velocity;
	}

	bool damageReceived()
	{
		if ((flags() & TAKE_DAMAGE) == TAKE_DAMAGE)
			return true;
		return false;
	}

protected:
	sf::Sprite _sprite;
	std::string _type;
	bool _killMe;
	bool _isInWater;
	sf::Vector2f _dimension;
	
	int _msX;
	int _msY;
	float _mass;

	int _component;

private:
	int _flags;
};

#endif // _ENTITY_H